import { generateUUID, transformHexColor } from '@renderer/utils/utils'
import { bgCanvas, canvas } from './canvasInstance'
import { Edge, EdgeView, Node } from '@antv/x6'
import { useMessageStore } from '../message/message'
import { storeToRefs } from 'pinia'
import { useCanvasParameterStore } from './canvasParameter'
import { useLayerStore } from '../resourceBar/layer'
import {
  addNumberToNode,
  arrangeSimData,
  changeEdgeAnchorPoints,
  changeEdgeSelect,
  changeEdgeSourceAnchorPoints,
  checkName,
  getPortType
} from './otherFun'

// #region 以下是渲染进程

// ================================================================================   画布

//显示画布属性
export const renderShowCanvasProperty = (): void => {
  const canvasProperties = window.api.handleCanvasData('getCanvasProperties', 'canvas2D', false, [])
  const data = {
    title: '画布属性',
    id: generateUUID(),
    type: 'canvas',
    data: canvasProperties
  }

  window.electron.ipcRenderer.send('openAttributeWindow', data)
}

// ================================================================================   节点

//显示节点属性
export const renderShowNodeProperty = (
  node: Node,
  type: 'node' | 'freeEdit' | 'plaintext' = 'node'
): void => {
  const nodeProperties = window.api.handleCanvasData('getNodes', 'canvas2D', false, ['id', node.id])
  const data = {
    title: '节点属性',
    id: generateUUID(),
    type: type,
    data: nodeProperties[0]
  }
  window.electron.ipcRenderer.send('openAttributeWindow', data)
}
//渲染进程添加节点
export const renderAddNode = (node: Node): void => {
  if (node.shape === 'edge-drag-node') {
    const { x, y } = node.position()

    const data = {
      id: node.id,
      shape: node.getData().shape,
      name: checkName(node.getData().name),
      sourceId: { x: x, y: y + 15 },
      sourcePortId: undefined,
      targetId: { x: x + 150, y: y + 15 },
      targetPortId: undefined,
      vertices: [],
      labels: [],
      zIndex: node.zIndex || -1,
      style: {
        width: 20,
        router: 'orth' as 'orth',
        connectorName: 'rounded' as 'rounded',
        connectorRadius: 20
      },
      simData: {
        path: '',
        belt: {
          speed: 10
        }
      }
    }
    window.api.handleCanvasData('addEdges', 'canvas2D', true, [data])
  } else if (node.shape === 'custom-port-node') {
    const data = {
      id: node.id,
      x: node.position().x,
      y: node.position().y,
      width: node.size().width,
      height: node.size().height,
      rotate: node.angle(),
      shape: node.shape,
      ports: [] as { id: string; group: string }[],
      points: '',
      name: checkName(node.getData().name),
      type: node.getData()?.type,
      zIndex: node.zIndex || -1,
      style: {
        borderColor: 'transparent',
        backgroundColor: '#d6ddff66'
      },
      simData: {}
    }
    window.api.handleCanvasData('addNodes', 'canvas2D', true, [data])
  } else {
    const data = {
      id: node.id,
      x: node.position().x,
      y: node.position().y,
      width: node.size().width,
      height: node.size().height,
      rotate: node.angle(),
      shape: node.shape,
      ports: [] as { id: string; group: string }[],
      name: checkName(node.getData().name),
      type: node.getData()?.type,
      zIndex: node.zIndex || -1,
      style: {
        backgroundColor: '#ffffff9c',
        borderWidth: 1,
        borderType: 'solid' as any,
        borderColor: '#cccccc',
        borderRadius: 0,
        icon: node.getData()?.icon,
        iconSize: 3
      },
      simData: {}
    }
    //整理ports
    const ports = node.getPorts() as any[]
    data.ports = ports

    const portsMsg = {
      portTop: getPortType(ports, 'top'),
      portRight: getPortType(ports, 'right'),
      portBottom: getPortType(ports, 'bottom'),
      portLeft: getPortType(ports, 'left')
    }
    data.style = {
      ...data.style,
      ...portsMsg
    }

    //整理simData
    const result = arrangeSimData(node)
    data.simData = result

    window.api.handleCanvasData('addNodes', 'canvas2D', true, [data])
  }
}
//渲染进程删除节点
export const renderDeleteNode = (ids: string | string[]): void => {
  const needDelEdgeIds = [] as string[]
  ids = Array.isArray(ids) ? ids : [ids]
  for (const id of ids) {
    const outputEdges = window.api.handleCanvasData('getEdges', 'canvas2D', false, ['sourceId', id])
    const inputEdges = window.api.handleCanvasData('getEdges', 'canvas2D', false, ['targetId', id])

    const outputEdgeIds = outputEdges.map((item) => item.id)
    const inputEdgeIds = inputEdges.map((item) => item.id)

    needDelEdgeIds.push(...outputEdgeIds, ...inputEdgeIds)
  }

  //先删除连接的线
  window.api.handleCanvasData('deleteEdges', 'canvas2D', true, [needDelEdgeIds])

  //给主进程发一个关闭仿真软体的消息
  window.electron.ipcRenderer.send('closeMechanical', ids)

  //再删除节点
  window.api.handleCanvasData('deleteNodes', 'canvas2D', true, [ids])

  //清空属性栏
  window.electron.ipcRenderer.send('openAttributeWindow', { type: null })
}
// 节点移动
export const renderNodeMove = (id: string, x: number, y: number): void => {
  window.api.handleCanvasData('moveNode', 'canvas2D', true, [id, x, y])
}
// 节点变换
export const renderNodeTransform = (id: string, width: number, height: number): void => {
  window.api.handleCanvasData('changeNodeSize', 'canvas2D', true, [id, width, height])
}
//显示节点批量编辑属性
export const renderNodeBulkEdit = (): void => {
  const data = {
    title: '批量节点',
    id: generateUUID(),
    type: 'bulkNode'
  }
  window.electron.ipcRenderer.send('openAttributeWindow', data)
}

// ================================================================================  边

//显示边属性
export const renderShowEdgeProperty = (edge: Edge): void => {
  const edgeProperties = window.api.handleCanvasData('getEdges', 'canvas2D', false, ['id', edge.id])
  if (edge.shape === 'conveyor-belt') {
    const data = {
      title: '边属性',
      id: generateUUID(),
      type: 'conveyor',
      data: edgeProperties[0]
    }
    window.electron.ipcRenderer.send('openAttributeWindow', data)
  } else if (edge.shape === 'road-edge') {
    const data = {
      title: '边属性',
      id: generateUUID(),
      type: 'road',
      data: edgeProperties[0]
    }
    window.electron.ipcRenderer.send('openAttributeWindow', data)
  } else {
    const data = {
      title: '边属性',
      id: generateUUID(),
      type: 'edge',
      data: edgeProperties[0]
    }
    window.electron.ipcRenderer.send('openAttributeWindow', data)
  }
}
//渲染进程边连接事件
export const renderEdgeConnect = (edge: Edge): void => {
  if (edge.shape === 'ordinary-edge') {
    const data = {
      id: edge.id,
      shape: edge.shape,
      name: checkName('普通边'),
      sourceId: edge.getSourceCellId(),
      sourcePortId: edge.getSourcePortId(),
      targetId: edge.getTargetCellId(),
      targetPortId: edge.getTargetPortId(),
      simData: {
        isTransport: false,
        transportId: ''
      }
    }
    //边连接边的处理
    changeEdgeSourceAnchorPoints(data)
    window.api.handleCanvasData('addEdges', 'canvas2D', true, [data])
    canvas.removeCell(edge)
  } else if (edge.shape === 'road-edge') {
    const edgeData = window.api.handleCanvasData('getEdges', 'canvas2D', false, ['id', edge.id])
    if (edgeData.length > 0) {
      const edgeItem = edgeData[0]
      window.api.handleCanvasData('deleteEdges', 'canvas2D', true, [edgeItem.id])

      edgeItem.id = generateUUID()
      const sourceItem = edge.getSource() as any
      if (sourceItem?.cell) {
        console.log(canvas.getCellById(edge.getSourceCellId()))
        edgeItem.sourceId = edge.getSourceCellId()
        edgeItem.sourcePortId = edge.getSourcePortId()
      } else {
        edgeItem.sourceId = edge.getSource() as any
      }
      const targetItem = edge.getTarget() as any
      if (targetItem?.cell) {
        edgeItem.targetId = edge.getTargetCellId()
        edgeItem.targetPortId = edge.getTargetPortId()
      } else {
        edgeItem.targetId = edge.getTarget() as any
      }

      window.api.handleCanvasData('addEdges', 'canvas2D', true, [edgeItem])
    } else {
      const data = {
        id: edge.id,
        shape: edge.shape,
        name: checkName('道路'),
        sourceId: '' as any,
        sourcePortId: '' as any,
        targetId: '' as any,
        targetPortId: '' as any,
        vertices: [],
        labels: [],
        zIndex: -1,
        style: {
          width: 20,
          router: 'orth' as 'orth',
          connectorName: 'rounded' as 'rounded',
          connectorRadius: 20
        },
        simData: {
          path: '',
          belt: {
            speed: 10
          }
        }
      }

      const sourceItem = edge.getSource() as any
      if (sourceItem?.cell) {
        console.log(canvas.getCellById(edge.getSourceCellId()))
        data.sourceId = edge.getSourceCellId()
        data.sourcePortId = edge.getSourcePortId()
      } else {
        data.sourceId = edge.getSource() as any
      }
      const targetItem = edge.getTarget() as any
      if (targetItem?.cell) {
        data.targetId = edge.getTargetCellId()
        data.targetPortId = edge.getTargetPortId()
      } else {
        data.targetId = edge.getTarget() as any
      }

      window.api.handleCanvasData('addEdges', 'canvas2D', true, [data])
    }

    canvas.removeCell(edge)
    const { isEdgeEdit } = storeToRefs(useCanvasParameterStore())
    isEdgeEdit.value = false
  }
}
//渲染进程删除边
export const renderDeleteEdge = (edgeIds: string | string[]): void => {
  edgeIds = Array.isArray(edgeIds) ? edgeIds : [edgeIds]
  window.api.handleCanvasData('deleteEdges', 'canvas2D', true, [edgeIds])
  window.electron.ipcRenderer.send('openAttributeWindow', { type: null })
}

// #region 以下是主进程

// ================================================================================  画布

//主进程更改了画布的属性
export const mainChangeCanvasProperties = (canvasProperties: any): void => {
  //判断canvas是否是一个空对象
  if (Object.keys(bgCanvas).length === 0) return
  //设置画布的背景
  bgCanvas.drawBackground({ color: canvasProperties.background })

  const gridColor = canvasProperties.gridColor
  const giridColor2 = transformHexColor(gridColor)

  //网格
  if (canvasProperties.showGrid) {
    bgCanvas.showGrid()
    bgCanvas.drawGrid({
      type: 'doubleMesh',
      args: [
        {
          color: giridColor2,
          thickness: 1,
          factor: 1
        },
        {
          color: gridColor,
          thickness: 1,
          factor: 10
        }
      ]
    })
  } else {
    bgCanvas.hideGrid()
  }

  //对齐线
  if (canvasProperties.enableSnapline) {
    canvas.enableSnapline()
  } else {
    canvas.disableSnapline()
  }
}
// 主进程重写画布
export const mainRewriteCanvas = (canvasData: any): void => {
  //判断canvas是否是一个空对象
  if (Object.keys(canvas).length === 0) return
  mainAddNode(canvasData.nodes)
  mainAddEdge(canvasData.edges)
}
//主进程清空画布
export const mainClearCanvas = (): void => {
  //判断canvas是否是一个空对象
  if (Object.keys(canvas).length === 0) return
  canvas.clearCells()
}
//主进程选择节点或边
export const mainSelectCell = (result: string[]): void => {
  //判断canvas是否是一个空对象
  if (Object.keys(canvas).length === 0) return

  const { lockNodeIds } = storeToRefs(useLayerStore())
  let ids = [] as string[]
  ids = result.filter((id: string) => !lockNodeIds.value.includes(id))

  const { selectedNode } = storeToRefs(useCanvasParameterStore())
  selectedNode.value = null
  changeEdgeSelect(null)
  canvas.cleanSelection()
  if (ids.length === 1) {
    const cell = canvas.getCellById(ids[0])
    if (canvas.isNode(cell)) {
      selectedNode.value = cell
    } else if (canvas.isEdge(cell)) {
      changeEdgeSelect(cell)
    }
  } else if (ids.length > 1) {
    const cells = ids.map((id) => canvas.getCellById(id))

    const { isCanvasSelect } = storeToRefs(useCanvasParameterStore())
    isCanvasSelect.value = false
    canvas.select(cells)

    setTimeout(() => {
      isCanvasSelect.value = true
    }, 100)
  }
}

// ================================================================================  节点

//主进程添加节点
export const mainAddNode = (nodes: any): void => {
  //判断canvas是否是一个空对象
  if (Object.keys(canvas).length === 0) return
  for (const node of nodes) {
    console.log(node)
    const addNode = canvas.addNode({
      shape: node.shape,
      id: node.id,
      x: node.x,
      y: node.y,
      width: node.width,
      height: node.height,
      ports: node.ports,
      data: {
        name: node?.name,
        type: node?.type,
        icon: node.style?.icon,
        ...node.style
      }
    })
    if (node.zIndex !== -1) {
      addNode.setZIndex(Number(node.zIndex))
    } else {
      node.zIndex = addNode.getZIndex()
      window.api.handleCanvasData('updateNodes', 'canvas2D', false, [node])
    }

    //如果是自由编辑区域
    if (node.shape === 'custom-port-node' && node.ports.length > 0) {
      addNode.attr('body/points', node.points)
    }

    addNumberToNode(addNode, node)

    //如果是纯文本节点
    if (node.type === 'plaintext') {
      const data = node.simData.plaintext
      addNode.setAttrByPath('label', data)
    }

    //给画布操作发消息
    useMessageStore().addCanvasOperate({
      source: '添加节点',
      content: `添加模型节点-${node.name}`
    })
  }
}
//主进程删除节点
export const mainDeleteNode = (nodes: any[]): void => {
  //判断canvas是否是一个空对象
  if (Object.keys(canvas).length === 0) return
  canvas.removeCells(nodes)

  //给画布操作发消息
  useMessageStore().addCanvasOperate({
    source: '节点删除',
    content: '节点删除数量',
    otherMsg: nodes.length.toString()
  })
}
//主进程节点更改属性
export const mainChangeNodeProperties = (nodes: any[]): void => {
  //判断canvas是否是一个空对象
  if (Object.keys(canvas).length === 0) return

  for (const node of nodes) {
    // 更改一些基本属性和样式属性
    const canvasNode = canvas.getCellById(node.id) as Node
    canvasNode.setPosition(node.x, node.y)
    canvasNode.setSize(node.width, node.height)
    canvasNode.rotate(node.rotate, {
      absolute: true
    })
    canvasNode.setData({
      name: node.name,
      ...node.style
    })
    if (node.zIndex !== -1) {
      canvasNode.setZIndex(Number(node.zIndex))
    }

    //处理一些特殊节点
    if (canvasNode.shape === 'custom-port-node') {
      canvasNode.setAttrByPath('body/fill', node.style?.backgroundColor)
      canvasNode.setAttrByPath('body/stroke', node.style?.borderColor)
    }

    addNumberToNode(canvasNode, node)

    //如果是纯文本节点
    if (node.type === 'plaintext') {
      const data = node.simData.plaintext
      canvasNode.setAttrByPath('label', data)
    }
  }
}
//主进程节点改变位置
export const mainChangeNodePosition = (node: any): void => {
  //判断canvas是否是一个空对象
  if (Object.keys(canvas).length === 0) return

  const canvasNode = canvas.getCellById(node.id) as Node
  canvasNode.setPosition(Number(node.x), Number(node.y))
}
//主进程节点改变尺寸
export const mainChangeNodeSize = (node: any): void => {
  //判断canvas是否是一个空对象
  if (Object.keys(canvas).length === 0) return

  const canvasNode = canvas.getCellById(node.id) as Node
  canvasNode.setSize(Number(node.width), Number(node.height))
}
//主进程改变节点连接桩
export const mainChangeNodePorts = (node: any): void => {
  if (!node) return
  //判断canvas是否是一个空对象
  if (Object.keys(canvas).length === 0) return

  const canvasNode = canvas.getCellById(node.id) as Node
  canvasNode.removePorts()
  canvasNode.addPorts(node.ports)
}

// ================================================================================  边

//主进程添加边
export const mainAddEdge = (edges: any[]): void => {
  //判断canvas是否是一个空对象
  if (Object.keys(canvas).length === 0) return
  for (const edge of edges) {
    if (edge.shape === 'ordinary-edge') {
      const resultEdge = canvas.addEdge({
        id: edge.id,
        shape: 'ordinary-edge',
        source: {
          cell: edge.sourceId,
          port: edge.sourcePortId
        },
        target: {
          cell: edge.targetId,
          port: edge.targetPortId
        },
        vertices: edge.vertices,
        router: {
          name: edge?.style?.router
        },
        connector: {
          name: edge?.style?.connectorName,
          args: {
            radius: edge?.style?.connectorRadius
          }
        },
        zIndex: edge.zIndex,
        attrs: {
          a1: {
            fill: edge.simData.isTransport ? '#0087dc' : '#ED8A19',
            stroke: edge.simData.isTransport ? '#0087dc' : '#ED8A19'
          }
        },
        data: {
          name: edge?.name
        }
      })
      //判断这条边的输入和输出是否是edge
      changeEdgeAnchorPoints(edge)
    } else if (edge.shape === 'conveyor-belt') {
      const beltEdge = canvas.addEdge({
        id: edge.id,
        shape: 'conveyor-belt',
        source: edge.sourceId,
        target: edge.targetId,
        vertices: edge.vertices,
        router: {
          name: edge?.style?.router
        },
        connector: {
          name: edge?.style?.connectorName,
          args: {
            radius: edge?.style?.connectorRadius
          }
        },
        data: {
          name: edge?.name
        }
      })

      if (edge.zIndex !== -1) {
        beltEdge.setZIndex(Number(edge.zIndex))
      } else {
        edge.zIndex = beltEdge.getZIndex()
        window.api.handleCanvasData('updateEdges', 'canvas2D', false, [edge])
      }

      setTimeout(() => {
        const beltView = canvas.findViewByCell(beltEdge) as EdgeView
        if (beltView) {
          const path = beltView.getConnectionPathData()
          edge.simData.path = path
          window.api.handleCanvasData('updateEdges', 'canvas2D', true, [edge])
        }
      }, 1000)
    } else if (edge.shape === 'road-edge') {
      const sourceId = edge.sourceId
      let source = null as any
      if (typeof sourceId === 'string') {
        source = {
          cell: sourceId,
          port: edge.sourcePortId
        }
      } else {
        source = sourceId
      }
      const targetId = edge.targetId
      let target = null as any
      if (typeof targetId === 'string') {
        target = {
          cell: targetId,
          port: edge.targetPortId
        }
      } else {
        target = targetId
      }
      const roadEdge = canvas.addEdge({
        id: edge.id,
        shape: 'road-edge',
        source: source,
        target: target,
        vertices: edge.vertices,
        router: {
          name: edge?.style?.router
        },
        connector: {
          name: edge?.style?.connectorName,
          args: {
            radius: edge?.style?.connectorRadius
          }
        },
        data: {
          name: edge?.name
        }
      })

      if (edge.zIndex !== -1) {
        roadEdge.setZIndex(Number(edge.zIndex))
      } else {
        edge.zIndex = roadEdge.getZIndex()
        window.api.handleCanvasData('updateEdges', 'canvas2D', false, [edge])
      }

      setTimeout(() => {
        const roadView = canvas.findViewByCell(roadEdge) as EdgeView
        if (roadView) {
          const path = roadView.getConnectionPathData()
          edge.simData.path = path
          window.api.handleCanvasData('updateEdges', 'canvas2D', true, [edge])
        }
      }, 1000)
    } else if (edge.shape === 'warning-line') {
      const beltEdge = canvas.addEdge({
        id: edge.id,
        shape: 'warning-line',
        source: edge.sourceId,
        target: edge.targetId,
        vertices: edge.vertices,
        router: {
          name: edge?.style?.router
        },
        connector: {
          name: edge?.style?.connectorName,
          args: {
            radius: edge?.style?.connectorRadius
          }
        },
        zIndex: edge.zIndex,
        data: {
          name: edge?.name
        }
      })
    }
  }

  const edge = edges[0]
  //给画布操作发消息
  if (edge.shape === 'ordinary-edge') {
    const source = canvas.getCellById(edge.sourceId)
    const target = canvas.getCellById(edge.targetId)
    useMessageStore().addCanvasOperate({
      source: '添加边',
      content: source.getData()?.name + '--> ' + target.getData()?.name
    })
  } else if (edge.shape === 'conveyor-belt') {
    useMessageStore().addCanvasOperate({
      source: '添加传送带',
      content:
        '起点 ' +
        `【${edge.sourceId.x + `，` + edge.sourceId.y}】` +
        '--> ' +
        '终点 ' +
        `【${edge.targetId.x + `，` + edge.targetId.y}】`
    })
  }
}
//主进程删除边
export const mainDeleteEdge = (edges: any[]): void => {
  //判断canvas是否是一个空对象
  if (Object.keys(canvas).length === 0) return
  canvas.removeCells(edges)

  //给画布操作发消息
  useMessageStore().addCanvasOperate({
    source: '边删除',
    content: '边删除数量',
    otherMsg: edges.length.toString()
  })
}
//主进程改变边属性
export const mainChangeEdgeProperties = (edges: any[]): void => {
  //判断canvas是否是一个空对象
  if (Object.keys(canvas).length === 0) return

  for (const edge of edges) {
    const canvasEdge = canvas.getCellById(edge.id) as Edge

    if (edge.shape === 'ordinary-edge') {
      if (edge.simData.isTransport) {
        canvasEdge.setAttrByPath('a1/fill', '#0087dc')
        canvasEdge.setAttrByPath('a1/stroke', '#0087dc')
      } else {
        canvasEdge.setAttrByPath('a1/fill', '#ED8A19')
        canvasEdge.setAttrByPath('a1/stroke', '#ED8A19')
      }
    } else {
      canvasEdge.prop('router/name', edge.style.router)
      canvasEdge.prop('connector/name', edge.style.connectorName)
      canvasEdge.prop('connector/args/radius', edge.style.connectorRadius)
    }

    if (edge?.labels && edge.labels.length > 0) {
      //先获取所有标签
      const oldLabels = canvasEdge.getLabels()
      //删除所有标签
      for (let i = oldLabels.length - 1; i >= 0; i--) {
        canvasEdge.removeLabelAt(i)
      }

      const newLabels = edge.labels as { text: string; distance: number }[]
      newLabels.forEach((label) => {
        canvasEdge.insertLabel({
          position: Number(label.distance),
          attrs: {
            rect: {
              fill: '#005aa2'
            },
            text: {
              text: label.text,
              stroke: '#fff',
              fontSize: 13,
              lineHeight: 20,
              refY: 2,
              textVerticalAnchor: 'middle'
            }
          }
        })
      })
    }

    if (edge.zIndex !== undefined) {
      canvasEdge.setZIndex(Number(edge.zIndex))
    }
  }
}
